bitkeeper revision 1.1236.1.19 (421e762a-grjFXfk-0fR1nd4ASovMA)
authorarun.sharma@intel.com[iap10] <arun.sharma@intel.com[iap10]>
Fri, 25 Feb 2005 00:49:46 +0000 (00:49 +0000)
committerarun.sharma@intel.com[iap10] <arun.sharma@intel.com[iap10]>
Fri, 25 Feb 2005 00:49:46 +0000 (00:49 +0000)
[PATCH] Support 1000 HZ guests

- Support guests with 1000 Hz
- cleanup the trailing garbage in vmx_virtpit.h
- Don't queue up pending timer interrupts before the first interrupt is injected
        - This fixes the low bogomips problem
- Protect xen against guests programming a bad value for the counter

Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
xen/arch/x86/vmx_intercept.c
xen/arch/x86/vmx_io.c
xen/include/asm-x86/vmx_virpit.h
xen/include/xen/lib.h

index 8427ffb1a38f6efd290d4a3dc1374f11f608865f..d9299d5c223458dc2139659bd2035a2fa51959bd 100644 (file)
@@ -203,7 +203,7 @@ static void pit_timer_fn(unsigned long data)
 
 
 /* Only some PIT operations such as load init counter need a hypervisor hook.
- * leave many other operations in user space DM
+ * leave all other operations in user space DM
  */
 void vmx_hooks_assist(struct exec_domain *d)
 {
@@ -213,11 +213,20 @@ void vmx_hooks_assist(struct exec_domain *d)
     struct vmx_virpit_t *vpit = &(d->arch.arch_vmx.vmx_platform.vmx_pit);
     int rw_mode;
 
-    if (p->state == STATE_IORESP_HOOK) { /*load init count*/
-        vpit->init_val = (p->u.data & 0xFFFF) ; /* frequency(ms) of pit */
-        vpit->period = (vpit->init_val) * 1000 / PIT_FREQ; /* frequency(ms) of pit */
+    /* load init count*/
+    if (p->state == STATE_IORESP_HOOK) { 
+        /* init count for this channel */
+        vpit->init_val = (p->u.data & 0xFFFF) ; 
+        /* frequency(ms) of pit */
+        vpit->period = DIV_ROUND(((vpit->init_val) * 1000), PIT_FREQ); 
+        if (vpit->period < 1) {
+            printk("VMX_PIT: guest programmed too small an init_val: %lx\n",
+                   vpit->init_val);
+            vpit->period = 1;
+        }
         vpit->vector = ((p->u.data >> 16) & 0xFF);
         vpit->channel = ((p->u.data >> 24) & 0x3);
+        vpit->first_injected = 0;
 
        vpit->count_LSB_latched = 0;
        vpit->count_MSB_latched = 0;
index d4a427a7f831dd9088a49d3c0c45268396a234f9..fcfe2ff36a7eaa669157e1b41269d9adc090b513 100644 (file)
@@ -367,6 +367,12 @@ void vmx_intr_assist(struct exec_domain *d)
     else
         clear_highest_bit(d, highest_vector); 
 
+    /* close the window between guest PIT initialization and sti */
+    if (highest_vector == vpit->vector && !vpit->first_injected){
+        vpit->first_injected = 1;
+        vpit->pending_intr_nr = 0;
+    }
+
     intr_fields = (INTR_INFO_VALID_MASK | INTR_TYPE_EXT_INTR | highest_vector);
     __vmwrite(VM_ENTRY_INTR_INFO_FIELD, intr_fields);
 
index 91a08c204d36f0b75fe5ed4eee7180ae78723dcf..35fe69c8440ffc6fecf0dfc7b5043404f7365384 100644 (file)
@@ -1,4 +1,3 @@
-
 #ifndef _VMX_VIRPIT_H
 #define _VMX_VIRPIT_H
 #include <xen/config.h>
@@ -25,6 +24,7 @@ struct vmx_virpit_t {
     unsigned int pending_intr_nr;      /* the couner for pending timer interrupts */
     unsigned long long inject_point;   /* the time inject virt intr */
     struct ac_timer pit_timer;         /* periodic timer for mode 2*/
+    int first_injected;                 /* flag to prevent shadow window */
 
     /* virtual PIT state for handle related I/O */
     int read_state;
@@ -40,42 +40,3 @@ struct vmx_virpit_t {
 extern void vmx_hooks_assist(struct exec_domain *d);
 
 #endif /* _VMX_VIRPIT_H_ */
-
-#ifndef _VMX_VIRPIT_H
-#define _VMX_VIRPIT_H
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/time.h>
-#include <xen/errno.h>
-#include <xen/ac_timer.h>
-#include <asm/vmx_vmcs.h>
-
-#define PIT_FREQ 1193181
-
-#define LSByte 0
-#define MSByte 1
-#define LSByte_multiple 2
-#define MSByte_multiple 3
-
-struct vmx_virpit_t {
-    /* for simulation of counter 0 in mode 2*/
-    int vector;                                /* the pit irq vector */
-    unsigned int period;               /* the frequency. e.g. 10ms*/
-    unsigned int channel;              /* the pit channel, counter 0~2 */
-    unsigned long *intr_bitmap;
-    unsigned int pending_intr_nr;      /* the couner for pending timer interrupts */
-    unsigned long long inject_point;   /* the time inject virt intr */
-    struct ac_timer pit_timer;         /* periodic timer for mode 2*/
-
-    /* virtual PIT state for handle related I/O */
-    int read_state;
-    int count_LSB_latched;
-    int count_MSB_latched;
-
-    unsigned int count;                /* the 16 bit channel count */
-    unsigned int init_val;     /* the init value for the counter */
-
-} ;
-
-#endif /* _VMX_VIRPIT_H_ */
index fb0e52c448fec8dd0e654251fe51f1a3a5728648..fb809de82a5aa8517051c2da9521f3863ecf1d1d 100644 (file)
@@ -23,6 +23,8 @@
 #define SWAP(_a, _b) \
    do { typeof(_a) _t = (_a); (_a) = (_b); (_b) = _t; } while ( 0 )
 
+#define DIV_ROUND(x, y) (((x) + (y) - 1) / (y))
+
 #define reserve_bootmem(_p,_l) ((void)0)
 
 struct domain;